package tray

import (
	"clipboard-tray/common/link"
	"embed"

	log "clipboard-tray/common/log"

	"github.com/getlantern/systray"
	"github.com/getlantern/systray/example/icon"
	"golang.design/x/clipboard"
)

//go:embed static/icon.ico
var f embed.FS

type Tray struct {
	ClipBoardUpdateChan chan struct{}
	clipItems           *link.Link
	clipMenuItems       []*clipMenuData
	titleMaxLength      int
	autorunName         string
	logger              *log.Log
}

type clipMenuData struct {
	menu *systray.MenuItem
	data string
}

func NewTray(clipItems *link.Link, logger *log.Log) *Tray {
	return &Tray{
		ClipBoardUpdateChan: make(chan struct{}, 1),
		clipItems:           clipItems,
		clipMenuItems:       make([]*clipMenuData, 0),
		titleMaxLength:      10,
		autorunName:         "CBH",
		logger:              logger,
	}
}

func (t *Tray) InitTray() {
	systray.Run(t.onReady, t.onExit)
}

func (t *Tray) onReady() {
	trayIcon, err := f.ReadFile("static/icon.ico")
	if err != nil {
		trayIcon = icon.Data
	}
	systray.SetTemplateIcon(trayIcon, trayIcon)
	systray.SetTitle("复制记录板")   // mac&linux
	systray.SetTooltip("复制记录板") // mac&win
	mAutorun := systray.AddMenuItemCheckbox("开机自启", "开机自启", t.checkAutoRun())
	mQuit := systray.AddMenuItem("退出", "退出")
	systray.AddSeparator()

	for {
		select {
		case <-mQuit.ClickedCh:
			systray.Quit()
			return
		case <-t.ClipBoardUpdateChan:
			t.AddClipBoardItem()
		case <-mAutorun.ClickedCh:
			if mAutorun.Checked() {
				t.unRegAutoRun()
				mAutorun.Uncheck()
			} else {
				t.regAutoRun()
				mAutorun.Check()
			}
		}
	}
}

func (t *Tray) AddClipBoardItem() {
	if t.clipItems.IsEmpty() {
		return
	}
	curNode := t.clipItems.Head.Next
	// 更新菜单复制选项
	for i, m := range t.clipMenuItems {
		if curNode == nil {
			break
		}
		m.menu.SetTitle(truncateStr(curNode.GetData(), t.titleMaxLength))
		m.menu.SetTooltip(curNode.GetData())
		t.clipMenuItems[i].data = curNode.GetData()
		curNode = curNode.Next
	}
	// 新建菜单复制选项
	for ; curNode != nil; curNode = curNode.Next {
		m := &clipMenuData{
			menu: systray.AddMenuItem(truncateStr(curNode.GetData(), t.titleMaxLength), curNode.GetData()),
			data: curNode.GetData(),
		}
		t.clipMenuItems = append(t.clipMenuItems, m)
		go func(menuString *string) {
			for range m.menu.ClickedCh {
				clipboard.Write(clipboard.FmtText, []byte(*menuString))
			}
		}(&m.data)
	}
}

func truncateStr(str string, maxLength int) string {
	arr := []rune(str)
	if len(arr) > maxLength {
		return string(arr[:maxLength]) + "..."
	}
	return str
}

func (t *Tray) onExit() {
	close(t.ClipBoardUpdateChan)
}
